﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.IO.Compression;
using System.Windows;
using System.Xml;

using KELT.ErrorControl;
using KELT.ErrorControl.CustomException;

using KELT;

namespace KELT.Files
{
    public class KELTFileControl
    {
        #region Param
        static String defaultDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\KELT";
        static String defaultWorkspaceDir = defaultDir + "\\Workspace";

        private static DirectoryInfo defaultDirInfo = new DirectoryInfo(defaultDir);
        private static DirectoryInfo defaultWorkspaceDirInfo = new DirectoryInfo(defaultWorkspaceDir);

        private static List<String> subFolderList = new List<string>();

        // 열고 닫은 파일 수 (임시폴더 생성 및 Untitled 이름 붙일 떄 사용)
        public static int fileCount = 0;

        #endregion

        public KELTFileControl()
        {
            CreateDefaultFolder();

            // 동기화 시 공유자원이 값타입 스태틱일 떄와 참조타입 스태틱일 때가 다름
            // http://skdd456.blog.me/50113127692
            lock (typeof(KELTFileControl))
            {
                if (subFolderList.Count == 0)
                {
                    subFolderList.Add("Object");
                    subFolderList.Add("Object\\Text");
                    subFolderList.Add("Object\\Image");
                    subFolderList.Add("Object\\Audio");
                    subFolderList.Add("Page");
                    subFolderList.Add("Timeline");
                }
            }
        }

        #region Foldering
        /**
         * 프로그램 삭제 시 Default Folder 삭제 할 것.
         * */
        public static void CreateDefaultFolder()
        {
            DirectoryInfo dirInfo = defaultDirInfo;

            if (!dirInfo.Exists)
            {
                // 기본 폴더 생성 안되있음.
                try
                {
                    dirInfo.Create();
                }
                catch (Exception e)
                {
                    ErrorManager.Instance.RecordError(e);

                    throw e;
                }
            }

            if (defaultWorkspaceDirInfo.Exists)
            {
                try
                {
                    defaultWorkspaceDirInfo.Create();
                }
                catch (Exception e)
                {
                    ErrorManager.Instance.RecordError(e);

                    throw e;
                }
            }

        }

        /// <summary>
        /// 
        /// *Exception*
        /// Exception e
        /// SameFolderExistException
        /// </summary>
        /// <returns>String created File Path</returns>
        public static string CreateTempKELTFileFolder() 
        {
            CreateDefaultFolder();

            DateTime dt = DateTime.Now;
            String curTIme = dt.ToString("yyyyMMddHHmmssfff");

            String xString = defaultWorkspaceDirInfo.ToString();
            xString += "\\" + curTIme;

            DirectoryInfo tempDir = new DirectoryInfo(xString);

            // 임시 디렉토리가 겹칠 경우 어떻게 할 꺼임?
            // DocumentName 이 동일 할 경우 겹치게 됨
            // 처음부터 시간을 활용하던지 임시 번호를 만들던지 할 것
            if (tempDir.Exists)
            {
                //tempDir.Delete(true);
                throw new SameFolderExistException(tempDir.ToString());
            }

            tempDir.Create();

            DirectoryInfo ObjectDir = new DirectoryInfo(tempDir.ToString() + "\\Object");
            if(!ObjectDir.Exists)
                ObjectDir.Create();
            {
                DirectoryInfo TextObjectDir = new DirectoryInfo(ObjectDir.ToString() + "\\Text");
                if(!TextObjectDir.Exists)
                    TextObjectDir.Create();

                DirectoryInfo ImageObjectDir = new DirectoryInfo(ObjectDir.ToString() + "\\Image");
                if(!ImageObjectDir.Exists)
                    ImageObjectDir.Create();

                DirectoryInfo SoundObjectDir = new DirectoryInfo(ObjectDir.ToString() + "\\Sound");
                if(!SoundObjectDir.Exists)
                    SoundObjectDir.Create();
            }

            DirectoryInfo TimelineDir = new DirectoryInfo(tempDir.ToString() + "\\Timeline");
            if (!TimelineDir.Exists)
                TimelineDir.Create();

            return tempDir.ToString();
        }

        public static void DeleteDefaultFolder()
        {
            DirectoryInfo dirInfo = defaultDirInfo;

            if (dirInfo.Exists)
            {
                DirectoryInfo[] directories = dirInfo.GetDirectories();

                foreach (DirectoryInfo di in directories)
                {
                    try
                    {
                        DeleteFolder(di.FullName, true);
                        di.Delete();
                    }
                    catch (Exception e)
                    {
                        ErrorManager.Instance.RecordError(e);

                        throw e;
                    }
                }
            }
        }

        public static void DeleteFolder(String dirPath, bool bRecursive)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(dirPath);

            if (bRecursive && dirInfo.Exists)
            {
                DirectoryInfo[] directories = dirInfo.GetDirectories();

                foreach (DirectoryInfo di in directories)
                {
                    try
                    {
                        DeleteFolder(di.FullName, bRecursive);
                        di.Delete();
                    }
                    catch (Exception e)
                    {
                        ErrorManager.Instance.RecordError(e);

                        throw e;
                    }
                }
            }

            FileInfo[] files = dirInfo.GetFiles();

            foreach (FileInfo fi in files)
            {
                try
                {
                    fi.Delete();
                }
                catch (Exception e)
                {
                    ErrorManager.Instance.RecordError(e);

                    throw e;
                }
            }
        }
        #endregion

        #region New
        public FileKELT makeProject(TOOL mainContext, FileKELT kelt)
        {
            //mainContext.init();

            if(kelt.tempFolderPath == null)
            {
                CreateDefaultFolder();
                kelt.tempFolderPath = CreateTempKELTFileFolder();
            }
            
            return kelt;
        }
        #endregion

        #region Save
        /**
         * 
         **/
        public void SaveKELT(FileKELT kelt, bool saveAs)
        {
            string xTempFolderPath = kelt.tempFolderPath;

            try
            {
                CreateDefaultFolder();
            }
            catch (Exception e)
            {
                ErrorManager.Instance.RecordError(e);
                return;
            }

            try
            {
                if (saveAs || !kelt.isSaved)
                {
                    // 다른 이름으로 저장
                    SaveKELTOtherName(kelt);
                }
                else
                {
                    SaveKELTUpdate(kelt);
                }

                kelt.Save();
            }
            catch (Exception e)
            {
                ErrorManager.Instance.RecordError(e);

                return;
            }

            try
            {
                // ZipFile.CreateFromDirectory(kelt.tempFolderPath, kelt.fileDirectory);
                //ZipFile.CreateFromDirectory(kelt.tempFolderPath, kelt.fileFullPath);
            }
            catch(Exception e)
            {
                ErrorManager.Instance.RecordError(e);
            }

            kelt.isLatestState = true;
            kelt.isSaved = true;
            

            // MainWindow TItle 이름 새로운 파일명으로 변경 할 것.
        }

        public void SaveKELTOtherName(FileKELT kelt)
        {
            // Save Dlg

            //Stream myStream;
            Microsoft.Win32.SaveFileDialog saveFileDialog = new Microsoft.Win32.SaveFileDialog();

            saveFileDialog.FileName = "UntitledKELT"; // Default File Name;
            saveFileDialog.DefaultExt = ".kelt";
            saveFileDialog.Filter = "KELT files (.kelt)|*.kelt|All files (*.*)|*.*";
            saveFileDialog.FilterIndex = 2;
            saveFileDialog.Title = "KELT File Save";
            saveFileDialog.RestoreDirectory = true;

            Nullable<bool> result = saveFileDialog.ShowDialog();

            if (result == true)
            {
                string fileName = saveFileDialog.FileName;

                kelt.fileDirectory = Path.GetDirectoryName(fileName);
                kelt.fileName = Path.GetFileNameWithoutExtension(fileName);
                kelt.fileExt = Path.GetExtension(fileName);

                // File Name 뭐라고 뜨는지 확인할 것.

                /*
                if ((myStream = saveFileDialog.OpenFile()) != null)
                {

                    myStream.Close();
                }
                 * */
            }
            else
            {
                throw new CancelSaveKELTFileException();
            }

            try
            {
                kelt.tempFolderPath = CreateTempKELTFileFolder();
            }
            catch (Exception e)
            {
                ErrorManager.Instance.RecordError(e);

                throw e;
            }


        }

        public static void SaveKELTUpdate(FileKELT kelt)
        {
            // 기존의 파일 덮어쓰기 할 것.
            // 기존의 임시 폴더 내용은 어떻게 처리할 지 결정할 것.
        }

        #endregion

        #region Load
        public static void LoadKELT(FileKELT kelt)
        {
            try
            {
                CreateDefaultFolder();
                kelt.tempFolderPath = CreateTempKELTFileFolder();
            }
            catch
            {
                // MessageBox "Fail Load"
                return;
            }

            //ZipFile.ExtractToDirectory(kelt.fileFullPath, kelt.tempFolderPath);

            // 기존에 Object 모두 초기화 할 것.
            // Object Loading.
        }
        #endregion
    }
}
